
local runtime = require 'jass.runtime'

local archive = {
    __call = function(self, data)
        for k, v in pairs(data) do
            self[k] = v
        end
        return self
    end,
}
setmetatable(archive, archive)

archive.allarchives = {}
archive.archivesmap = {}
archive.archivesenm = {}

archive.tooltips = {

    art = function(self)
        if not self:is_enable() then 
            return japi.GetDisabledIcon(self.art)
        end 
        return self.art
    end,

    tip = function(self)
        return self.tip
    end,

    ubertip = function(self)
        return self.ubertip_ui
    end,

    requires = function(self)
        return self.require_ui
    end,

    usedtip = function(self)
        return self.usedtip
    end,

    soldtip = function(self)
        return self.soldtip
    end,

    message = function(self)
        return self.message
    end,

    description = function(self)
        return self.description
    end,

}

local mt = { }
archive.__index = mt 

-- 结构
mt.type = "archive"

-- 图标
mt.art = "ReplaceableTextures\\CommandButtons\\BTNability_hunter_cobrashot.blp"

-- 标题
mt.tip = "成就"

-- 描述
mt.ubertip = ""


-- 异步的 返回true则进行同步
-- function mt:on_click(player) return false end;

-- 点击之后 同步的
-- function mt:on_clicked(player) end;

-- 玩家英雄初始化调用
-- function mt:of_hero() end;
    
-- 初始化
-- function mt:on_init() end;

--[执行事件]
function mt:notify(name, ...)
    local func = self[name]
    if func then 
        return select(2, xpcall(func, runtime.error_handle, self, ...))
    end 
end 

-- 是激活的项目
function mt:is_enable()
    return self.enable_flag == true
end 

-- 激活
function mt:enable()
    self.enable_flag = true 
    self:refresh()
end 

-- 关闭
function mt:disable()
    self.enable_flag = false  
    self:refresh()
end 

function mt:get_art()
    if not self:is_enable() then 
        return japi.GetDisabledIcon(self.art)
    end 
    return self.art
end 

function mt:get_tip()
    return self.tip 
end 

function mt:get_ubertip()
    return self.ubertip_ui
end 

function mt:refresh()
    if not self:is_enable() then 
        self.require_ui = ("|cffffcc00需要:|r|n|cffc0c0c0 - %s|r"):format(self.requires)
    else
        self.require_ui = nil
    end 
    self.ubertip_ui = string.formatter(self.ubertip, self)
end 

-- 获取UI信息
function mt:get_tooltips(name)
    if name and archive.tooltips[name] then
        return archive.tooltips[name](self)
    end
end

function mt:remove()
    if self.removed then return end; 
    self.removed = true

    local owner = self.owner 
    local label = self.label 

    local name = self.name 
    owner.archives[label][name] = nil

    self:notify("on_deallocate")
end

--[[
    注册一个成就，然后 获取模板的数据，如果获取不到直接报错，
    获取到之后存到玩家身上，reload 的时候全部销毁

    加一个方法来遍历玩家的成就
    可以直接根据名字获取玩家的成就

    玩家初始话的时候执行 on_initialize_player
    玩家注册英雄的时候执行 on_initialize_hero
    销毁的情况下析构执行 on_deallocate 

]]

ac.game:on "游戏-即将热更新" (function ()
    local archivesenm = archive.archivesenm
    archive.allarchives = { }
    archive.archivesmap = { }
    archive.archivesenm = { }
    for _, object in ipairs(archivesenm) do 
        object:remove() 
    end 
end)

-- 注册
function ac.player.__index:register_archive(label, name)
    local template = archive.allarchives[label][name]
    if not template then 
        log.error("注册空的archive对象", label, name)
        return 
    end 
    self.archives[label] = self.archives[label] or { }
    local object = setmetatable({owner = self, label = label,}, template.meta)
    object:notify("on_initialize")
    object:refresh()
    self.archives[label][name] = object
    table.insert(archive.archivesenm, object)
    self:notify("玩家-注册成就", self, label, object)
    return object
end 

-- 获取
function ac.player.__index:get_archive(label, name)
    if self.archives[label] then 
        return self.archives[label][name]
    end
end 

function ac.player.__index:search_archives(label) 
    local list = { }
    local info = archive.archivesmap[label]
    if info then  
        for i, name in ipairs(info) do 
            local data = self:get_archive(label, name)
            if data then 
                list[#list+1] = data
            end 
        end 
    end
    return list
end 

ac.archive = setmetatable({}, {
    __index = archive,
    __call = function(self, label, name)
        if not archive.allarchives[label] then 
            archive.allarchives[label] = {}
            archive.archivesmap[label] = {}
        elseif archive.allarchives[label][name] then 
            return archive.allarchives[label][name]
        end 
        local data = { }
        data.type = label
        data.name = name
        data.meta = {
            __index = data,
            -- __gc = function(t)
            --     print( t.owner, t.name, "释放内存")
            -- end,
        }
            

        setmetatable(data, archive)
        archive.allarchives[label][name] = data
        table.insert(archive.archivesmap[label], name)
        return data
    end,
})

return archive